package com.basemap;

import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.FutureTarget;
import com.esri.arcgisruntime.concurrent.ListenableFuture;
import com.esri.arcgisruntime.data.Feature;
import com.esri.arcgisruntime.data.FeatureQueryResult;
import com.esri.arcgisruntime.data.FeatureTable;
import com.esri.arcgisruntime.data.GeoPackage;
import com.esri.arcgisruntime.data.GeoPackageFeatureTable;
import com.esri.arcgisruntime.data.QueryParameters;
import com.esri.arcgisruntime.geometry.Envelope;
import com.esri.arcgisruntime.geometry.Geometry;
import com.esri.arcgisruntime.layers.FeatureLayer;
import com.esri.arcgisruntime.loadable.LoadStatus;
import com.esri.arcgisruntime.symbology.SimpleFillSymbol;
import com.esri.arcgisruntime.symbology.SimpleLineSymbol;
import com.esri.arcgisruntime.symbology.SimpleRenderer;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 天地图离线需要计算，通过行政区范围，现在行政区来计算下载，暂时先不弄，没有行政区范围
 * 2024年7月31日11:57:14
 */
public class TianDiTuDownload {


    public void downMapText(Context context) {

        this.context = context;

        loadCity(new BaceCallBack.MsgCallBack() {
            @Override
            public void execute(boolean msg) {

                getGzGeometry(new BaceCallBack.QueryGpkgCallBack() {
                    @Override
                    public void queryGpkgFeature(Feature f) {
                        Geometry geometry = f.getGeometry();
                        Envelope extent = geometry.getExtent();
                        downMap(extent);
                    }
                });

            }
        });

    }

    FeatureLayer gzFeatureLayer = null;

    private void loadCity(BaceCallBack.MsgCallBack msgCallBack) {
        GeoPackage gzGeoPackage = new GeoPackage("Constants.rootPath" + File.separator + "city.gpkg");
        gzGeoPackage.loadAsync();
        gzGeoPackage.addDoneLoadingListener(() -> {
            if (gzGeoPackage.getLoadStatus() == LoadStatus.LOADED) {
                List<GeoPackageFeatureTable> geoPackageFeatureTables = gzGeoPackage.getGeoPackageFeatureTables();
                for (int i = 0; i < geoPackageFeatureTables.size(); i++) {
                    //加载图层
                    FeatureTable geoPackageTable = gzGeoPackage.getGeoPackageFeatureTables().get(i);
                    gzFeatureLayer = new FeatureLayer(geoPackageTable);
                    switch (geoPackageTable.getTableName()) {
                        case "city": {

                            SimpleFillSymbol simpleFillSymbol = new SimpleFillSymbol(SimpleFillSymbol.Style.SOLID, Color.parseColor("#FFFFFF"),
                                    new SimpleLineSymbol(SimpleLineSymbol.Style.DASH, Color.parseColor("#000000"), 1.0f));

                            SimpleRenderer renderer = new SimpleRenderer(simpleFillSymbol);

                            gzFeatureLayer.setRenderer(renderer);
                            gzFeatureLayer.setVisible(false);
                            msgCallBack.execute(true);
                        }
                    }
                }
            }
        });
    }


    private void getGzGeometry(BaceCallBack.QueryGpkgCallBack queryGpkgCallBack) {
        if (gzFeatureLayer != null) {
            QueryParameters query = new QueryParameters();
            query.setWhereClause("PAC ='520102'");
            ListenableFuture<FeatureQueryResult> future = gzFeatureLayer.selectFeaturesAsync(query, FeatureLayer.SelectionMode.NEW);
            future.addDoneListener(() -> {
                try {
                    FeatureQueryResult result = future.get();
                    Iterator<Feature> iterator = result.iterator();

                    //遍历筛选结果
                    while (iterator.hasNext()) {
                        //获取选中要素的属性数据及空间数据
                        Feature feature = iterator.next();
                        queryGpkgCallBack.queryGpkgFeature(feature);
                    }
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
    }

    //影像 - 等经纬度
    public static String img_c = "http://{server}.tianditu.gov.cn/img_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
    //影像注记 - 等经纬度
    public static String cia_c = "http://{server}.tianditu.gov.cn/cia_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";

//    //矢量（行政） - 等经纬度
//    public static String vec_c = "http://{server}.tianditu.gov.cn/vec_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
//    //矢量（行政） - 墨卡托
//    public static String vec_w = "http://{server}.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
//    //矢量注记（行政） - 等经纬度
//    public static String cva_c = "http://{server}.tianditu.gov.cn/cva_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
//    //矢量注记（行政） - 墨卡托
//    public static String cva_w = "http://{server}.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
    //影像 - 墨卡托
//    public static String img_w = "http://{server}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
    //影像注记 - 墨卡托
//    public static String cia_w = "http://{server}.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
    //地形 - 等经纬度
//    public static String ter_c = "http://{server}.tianditu.gov.cn/ter_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
//    //地形 - 墨卡托
//    public static String ter_w = "http://{server}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
//    //地形注记 - 等经纬度
//    public static String cta_c = "http://{server}.tianditu.gov.cn/cta_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cta&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
//    //地形注记 - 墨卡托
//    public static String cta_w = "http://{server}.tianditu.gov.cn/cta_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cta&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";

    //    public static String[] servers = {"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"};
    public static String[] servers = {"t1"};


    private Context context;

    public void downMap(Envelope extent) {


        //这里放你的天地图开发者秘钥，注意天地图API访问次数限制
        String tk = "91d01a0e78376798899b480381dffab1";

        String[] urlArr = {img_c, cia_c};//要下载的图层


        ExecutorService exe = Executors.newFixedThreadPool(6);

        //等经纬度第一层是1x2，纬度数量是2^0，经度数量是2^1
        //墨卡托投影第一层是2x2，纬度数量是2^1，经度数量是2^1
        for (int i = 0; i < urlArr.length; i++) {
            String url = urlArr[i].replace("{tk}", tk);
            System.out.println(url);
            String layerName = url.split("tianditu.gov.cn/")[1].split("/wmts?")[0];
            System.out.println(layerName);
            if (layerName.endsWith("c")) {
                new Thread(() -> {
                    int minZoom = 15;
                    int maxZoom = 18;

                    double xMax = extent.getXMax();
                    double xMin = extent.getXMin();
                    double yMax = extent.getYMax();
                    double yMin = extent.getYMin();

                    double startLat = yMax;//开始纬度（从北到南）
                    double endLat = yMin;//结束纬度（从北到南）
                    double startLon = xMin;//开始经度（从西到东）
                    double endLon = xMax;//结束经度（从西到东）
//                            double startLat = 53.58;//开始纬度（从北到南）
//                            double endLat = 2.7;//结束纬度（从北到南）
//                            double startLon = 73.2;//开始经度（从西到东）
//                            double endLon = 135.15;//结束经度（从西到东）
                    //等经纬度
                    for (int z = minZoom; z <= maxZoom; z++) {
                        double deg = 360.0 / Math.pow(2, z) / 256;//一个像素点代表多少度
                        int startX = (int) ((startLon + 180) / deg / 256);//减数取整
                        int endX = (int) ((endLon + 180) / deg / 256);//加数取整
                        int startY = (int) ((90 - startLat) / deg / 256);
                        int endY = (int) ((90 - endLat) / deg / 256);
                        for (int y = startY; y <= endY; y++) {
                            for (int x = startX; x <= endX; x++) {
                                final String newUrl = url.replace("{server}", servers[(int) (Math.random() * servers.length)]).replace("{z}", z + "").replace("{y}", y + "").replace("{x}", x + "");
                                //System.out.println(newUrl);
                                final String filePath = "Constants.getdownMapPath()" + "/" + layerName + "/" + z + "/" + y + "/" + x + ".png";
//                            exe.execute(new Runnable() {
//                                @Override
//                                public void run() {
                                File file = new File(filePath);
                                if (!file.exists()) {
                                    if (!file.getParentFile().exists()) {
                                        file.getParentFile().mkdirs();
                                    }
                                    boolean loop = true;
                                    int count = 0;
                                    while (loop && count < 5) {//下载出错进行重试，最多5次
                                        count++;
                                        try {
                                            InputStream in = getFileInputStream(newUrl);
                                            OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
                                            byte[] b = new byte[8192];
                                            int len = 0;
                                            while ((len = in.read(b)) > -1) {
                                                out.write(b, 0, len);
                                                out.flush();
                                            }
                                            out.close();
                                            in.close();
                                            loop = false;
                                        } catch (Exception e) {
                                            loop = true;
                                        }
                                    }
                                    if (loop) {
                                        System.out.println("下载失败：" + newUrl);
                                    }
                                }
//                                }
//                            });
                            }
                        }
                    }
                }).start();


            }
//            else {
//                //墨卡托
//
//                /**
//                 * earthRadius = 6378137;//地球赤道半径6378137米
//                 * aa = earthRadius * (Math.PI - 0);//赤道周长的一半，20037508.3427892
//                 * 85.05112877980659 = (Math.atan(Math.exp(aa / earthRadius))-Math.PI/4)*2 * 180 / Math.PI;//墨卡托最大有效纬度
//                 */
//                if (startLat > 85.051128) {
//                    System.out.println("墨卡托投影起始纬度最大为：85.051128，下载区域将被限定。");
//                    startLat = 85.051128;
//                }
//                if (endLat < -85.051128) {
//                    System.out.println("墨卡托投影终止纬度最小为：-85.051128，下载区域将被限定。");
//                    endLat = -85.051128;
//                }
//
//                for (int z = minZoom; z <= maxZoom; z++) {
//                    if (z > 10) {//天地图10级以上只有中国区域
//                        startLat = startLat > xMin ? xMin : startLat;//开始纬度（从北到南）
//                        endLat = endLat < yMin ? yMin : endLat;//结束纬度（从北到南）
//                        startLon = startLon < xMax ? xMax : startLon;//开始经度（从西到东）
//                        endLon = endLon > yMax ? yMax : endLon;//结束经度（从西到东）
//                    }
//                    double deg = 360.0 / Math.pow(2, z) / 256;//一个像素点代表多少度
//                    int startX = (int) ((startLon + 180) / deg / 256);
//                    int endX = (int) ((endLon + 180) / deg / 256);
//                    /**
//                     * 这里是基于等经纬度坐标转墨卡托坐标的公式得到的算法。（）
//                     * 先算出当前地图级别下纬度方向用该有多少个像素点（一个瓦片是256个点，一共有Math.pow(2, z)个瓦片）
//                     * 再算出指定纬度坐标与赤道的距离（北半球为正南半球为负）（这里抵消了带入赤道周长的计算，因为它是一个固定值，把赤道周长定为1就抵消了）：Math.log(Math.tan((90 + startLat) * Math.PI / 360)) / (Math.PI / 180)
//                     * 就可以得到纬度坐标距赤道有多少个点：(Math.log(Math.tan((90 + startLat) * Math.PI / 360)) / (Math.PI / 180)) / (360/Math.pow(2, z)/256) + 0.5)
//                     * 然后就可以计算出其瓦片坐标。
//                     */
//                    int startY = (((int) Math.pow(2, z) * 256 / 2) - (int) ((Math.log(Math.tan((90 + startLat) * Math.PI / 360)) / (Math.PI / 180)) / (360 / Math.pow(2, z) / 256) + 0.5)) / 256;
//                    int endY = (((int) Math.pow(2, z) * 256 / 2) - (int) ((Math.log(Math.tan((90 + endLat) * Math.PI / 360)) / (Math.PI / 180)) / (360 / Math.pow(2, z) / 256) + 0.5)) / 256;
//                    for (int y = startY; y <= endY; y++) {//加入判断是等经纬度还是墨卡托
//                        for (int x = startX; x <= endX; x++) {
//                            final String newUrl = url.replace("{server}", servers[(int) (Math.random() * servers.length)]).replace("{z}", z + "").replace("{y}", y + "").replace("{x}", x + "");
//                            //System.out.println(newUrl);
//                            final String filePath = Constants.getdownMapPath() + "/" + layerName + "/" + z + "/" + y + "/" + x + ".png";
//                            exe.execute(new Runnable() {
//                                @Override
//                                public void run() {
//                                    File file = new File(filePath);
//                                    if (!file.exists()) {
//                                        if (!file.getParentFile().exists()) {
//                                            file.getParentFile().mkdirs();
//                                        }
//                                        boolean loop = true;
//                                        int count = 0;
//                                        while (loop && count < 5) {//下载出错进行重试，最多5次
//                                            count++;
//                                            try {
//                                                InputStream in = getFileInputStream(newUrl);
//                                                OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
//                                                byte[] b = new byte[8192];
//                                                int len = 0;
//                                                while ((len = in.read(b)) > -1) {
//                                                    out.write(b, 0, len);
//                                                    out.flush();
//                                                }
//                                                out.close();
//                                                in.close();
//                                                loop = false;
//                                            } catch (Exception e) {
//                                                loop = true;
//                                            }
//                                        }
//                                        if (loop) {
//                                            System.out.println("下载失败：" + newUrl);
//                                        }
//                                    }
//                                }
//                            });
//                        }
//                    }
//                }
//            }
        }
        exe.shutdown();
        while (true) {
            try {
                Thread.sleep(1000L);//主线程休眠1秒，等待线程池运行结束，同时避免一直死循环造成CPU浪费
            } catch (InterruptedException e) {
            }
            if (exe.isTerminated()) {//线程池所有线程都结束运行
                break;
            }
        }
    }

    //获取文件下载流
    public InputStream getFileInputStream(String url) throws Exception {
        FutureTarget<File> submit = null;
        submit = Glide.with(context)
                .asFile()
                .load(url)
                .error((Drawable) null)
                .submit();
        File file = submit.get();

        FileInputStream inputStream = new FileInputStream(file);
        return inputStream;
    }

}
